home *** CD-ROM | disk | FTP | other *** search
/ PC World Interactive 7 / PC World Interactive 7.iso / program / ctutor.exe / SOURCE / DATA.C < prev    next >
C/C++ Source or Header  |  1994-05-15  |  15KB  |  452 lines

  1. /* DATA.C - Data initialize and calculate                          */
  2. /* Copyright (c) 1994 Coronado Enterprises                         */
  3.  
  4. #include <ctype.h>
  5. #include <string.h>
  6. #include <math.h>
  7. #include "vc.h"
  8. #include "video.h"
  9.  
  10. extern struct vars allvars[];
  11. extern char inline[];
  12. extern int col;
  13. extern int errcode, colerr;
  14. extern char strngout[];
  15.  
  16.  
  17.  
  18. /******************************************************** initdata */
  19. /* This function is used to initialize all of the variables to the */
  20. /*  starting values including their variable names.                */
  21. void initdata(struct vars *pnt)
  22. {
  23. int index;
  24.     for (index = 0 ; index < 6 ; ++index) {
  25.        (pnt+index)->varname[0] = 'A' + index;
  26.        (pnt+index)->varname[1] = 0;
  27.        (pnt+index)->outtype = 'F';
  28.        (pnt+index)->value = 0.0;
  29.     }
  30.     for (index = 6 ; index < 12 ; ++index) {
  31.        (pnt+index)->varname[0] = 'I' + index - 6;
  32.        (pnt+index)->varname[1] = 0;
  33.        (pnt+index)->outtype = 'D';
  34.        (pnt+index)->value = 0;
  35.     }
  36.     (pnt+4)->value = 2.718281828459045;
  37.     (pnt+5)->value = 3.141592653589793;
  38.     (pnt+11)->value = 16777215;
  39. }
  40.  
  41.  
  42.  
  43. /******************************************************** getnames */
  44. /* This function reads in a new list of variable names to be used  */
  45. /*  in place of the names A to F. This is only as a convenience    */
  46. /*  for the user, so he can use more meaningful names.             */
  47. void getnames(void)
  48. {
  49. char var, index;
  50. char dummy[80];
  51.  
  52.    col = 1;                     /* skip over and ignore the # sign */
  53.    do {
  54.       if (inline[col] == ' ') 
  55.          col++;                   /* ignore all leading blanks     */
  56.       else {
  57.          var = inline[col] - 'A';
  58.          if ((var >= 0) && (var <= 5)) {  /* A through F           */
  59.             col++;
  60.             if (inline[col] != '-') {     /* should be a dash      */
  61.                errchk(14);
  62.                errout();
  63.                return;
  64.             }
  65.             col++;
  66.             for (index = 0 ; index < 6 ; index++) {
  67.                if (isalpha(inline[col]) || isdigit(inline[col])) {
  68.                   dummy[index] = inline[col];
  69.                   dummy[index + 1] = 0;
  70.                   col++;
  71.                }
  72.             }
  73.             if (index > 0) {
  74.                strcpy(allvars[var].varname, dummy);
  75.                strcpy(strngout, "      ");  /* this is for         */
  76.                strngout[6 - strlen(dummy)] = 0;  /* leading blanks */
  77.                strcat(strngout, dummy);
  78.                strngdis_val(var + 1, 1);
  79.             }
  80.          } else if ((var >= 8) && (var <= 13)) {  /* I through N   */
  81.             col++;
  82.             if (inline[col] != '-') { /* should be a dash          */
  83.                errchk(14);
  84.                errout();
  85.                return;
  86.             }
  87.             col++;
  88.             if ((inline[col] == 'O') || (inline[col] == 'D') ||
  89.                       (inline[col] == 'H') || (inline[col] == 'X')) {
  90.                var -= 2;
  91.                allvars[var].outtype = inline[col];
  92.                col++;
  93.             }
  94.             else {
  95.                errchk(15);
  96.                errout();
  97.                return;
  98.             }
  99.          }
  100.          else {                       /* unknown variable name     */
  101.             errchk(3);
  102.             errout();
  103.             return;
  104.          }
  105.       }
  106.    } while (inline[col] && (errcode == 0));
  107. }
  108.  
  109.  
  110.  
  111. /******************************************************** calcdata */
  112. /* This is the function that actually does the work of deciding    */
  113. /*  what calculations need to be done. The method used is          */
  114. /*  described in detail below.                                     */
  115. /*    Three variables and two operators are         number1        */
  116. /*    stored as per the list. "op1" is always         op1          */
  117. /*    a plus or minus, and op2 is always a          number2        */
  118. /*    multiplication or divide. If a plus or          op2          */
  119. /*    minus is found for op2, number1 and           number3        */
  120. /*    number2 are combined according to op1                        */
  121. /*    and the result becomes number1, the new op2 becomes op1, and */
  122. /*    number3 becomes number2. If op2 is either a multiplication   */
  123. /*    or divide, number2 and number3 are combined according to op2 */
  124. /*    and the result is placed in number2. When a parentheses is   */
  125. /*    found, a recursive call is made and the expression in the    */
  126. /*    parentheses is evaluated. A bit of study will be very        */
  127. /*    fruitful in understanding this operation.                    */
  128. void calcdata(double *newval)
  129. {
  130. double number1, number2, number3, getnum();
  131. char op1, op2, getop();
  132.  
  133.    number1 = 0.0;
  134.    op1 = '+';
  135.    number2 = 0.0;
  136.    while (inline[col] == ' ') 
  137.       col++;                      /* ignore blanks                 */
  138.                                   /* check for unary operator      */
  139.    if ((inline[col] == '+') || (inline[col] == '-')) {
  140.       op1 = inline[col];
  141.       col++;
  142.    }
  143.  
  144.    number2 = getnum();         /* (inline[col]== 0 ) = End of line */
  145.                                /* (inline[col]=='$') = End of line */
  146.    if ((inline[col] == 0) || (inline[col] =='$')) {
  147.       calcdat(&number1, &op1, &number2);
  148.       *newval = number1;
  149.       return;
  150.    }
  151.    for ( ; ; ) {
  152.       op2 = getop();
  153.       col++;
  154.                               /* check for end of line  0, ), or $ */
  155.       if (op2 == '$') 
  156.          op2 = 0;                 /* force a $ to lool like eol    */
  157.       if ((op2 == 0) || (op2 == ')')) {
  158.          col++;
  159.          calcdat(&number1, &op1, &number2);
  160.          *newval = number1;
  161.          return;
  162.       }
  163.       number3 = getnum();
  164.       if ((op2 == '*') || (op2 == '/')){
  165.          calcdat(&number2, &op2, &number3);
  166.       } else {
  167.          calcdat(&number1, &op1, &number2);
  168.          op1 = op2;
  169.          number2 = number3;
  170.       }
  171.    } /* end of infinite for loop */
  172. }
  173.  
  174.  
  175.  
  176. /********************************************************* calcdat */
  177. /* This function actually does the calculations described in the   */
  178. /*  function above.                                                */
  179. void calcdat(double *number1, char *op1, double *number2)
  180. {
  181.    switch (*op1) {
  182.       case '*' : *number1 = (*number1) * (*number2);
  183.                  break;
  184.       case '/' : if (*number2 == 0.0) {
  185.                      errchk(10);
  186.                      break;
  187.                  }
  188.                  *number1 = (*number1) / (*number2);
  189.                  break;
  190.       case '+' : *number1 = *number1 + *number2;
  191.                  break;
  192.       case '-' : *number1 = *number1 - *number2;
  193.                  break;
  194.       default  : break;
  195.    }
  196.    return;
  197. }
  198.  
  199.  
  200.  
  201. /********************************************************** getnum */
  202. /* This is the workhorse of the program. It actually scans the     */
  203. /*  data input field and converts the data into numbers which are  */
  204. /*  in the internal format of the computer so the calculations can */
  205. /*  be done.                                                       */
  206. double getnum(void)
  207. {
  208. int index, i, decpt;
  209. double newval;
  210. char name[7];
  211. double sqrt(), exp(), log(), sin(), cos(), atan();
  212.  
  213.    while (inline[col] == ' ') 
  214.       col++;                    /* ignore blanks                   */
  215.  
  216.    index = inline[col];
  217.    if (index == '(') {
  218.        col++;
  219.        calcdata(&newval);       /* recursive call                  */
  220.        col--;
  221.        return(newval);
  222.    }
  223.  
  224.    decpt = 0;                   /* search for a decimal point      */
  225.    i = col;
  226.    index = inline[i];
  227.    while ((index >= '0') && (index <= '9')) {
  228.       i++;
  229.       index = inline[i];
  230.       if (index == '.') 
  231.          decpt = 1;
  232.    }
  233.  
  234.    index = inline[col];
  235.    if (((index > '0') && (index <= '9')) ||
  236.              ((index == '0') && (decpt == 1))  ||
  237.                     (index == '.')) {  /* floating number          */
  238.       newval = 0.0;
  239.       while ((index >= '0') && (index <= '9')) {
  240.          newval = 10.0 * newval + (index - '0');
  241.          col++;
  242.          index = inline[col];
  243.       }
  244.       if (index == '.') {
  245.          double constant = 0.1;
  246.          col++;
  247.          index = inline[col];
  248.          while ((index >= '0') && (index <= '9')) {
  249.             newval = newval + (index - '0') * constant;
  250.             constant *= 0.1;
  251.             col++;
  252.             index = inline[col];
  253.          }
  254.       }
  255.       return(newval);
  256.    }                            /* end of floating point number    */
  257.  
  258.    if (index == '0') {          /* octal or hexadecimal            */
  259.       col++;
  260.       index = inline[col];
  261.       if ((index == 'x') || (index == 'X')){ /* hexadecimal        */
  262.          col++;
  263.          index = inline[col];
  264.          newval = 0.0;
  265.          while (((index >= '0') && (index <= '9')) ||
  266.                 ((index >= 'A') && (index <= 'F')) ||
  267.                 ((index >= 'a') && (index <= 'f'))) {
  268.             switch (index) {
  269.                case '0':
  270.                case '1':
  271.                case '2':
  272.                case '3':
  273.                case '4':
  274.                case '5':
  275.                case '6':
  276.                case '7':
  277.                case '8':
  278.                case '9':i = index - '0';
  279.                         break;
  280.                case 'A':
  281.                case 'B':
  282.                case 'C':
  283.                case 'D':
  284.                case 'E':
  285.                case 'F':i = index - 'A' + 10;
  286.                         break;
  287.                case 'a':
  288.                case 'b':
  289.                case 'c':
  290.                case 'd':
  291.                case 'e':
  292.                case 'f':i = index - 'a' + 10;
  293.                         break;
  294.                default :break;
  295.             }
  296.             newval = 16.0 * newval + i;
  297.             col++;
  298.             index = inline[col];
  299.          }
  300.       return(newval);
  301.       }                         /* end of hexadecimal 'if'         */
  302.  
  303.       else {                    /* octal                           */
  304.          newval = 0.0;
  305.          while ((index >= '0') && (index <= '7')) {
  306.             newval = 8.0 * newval + (index - '0');
  307.             col++;
  308.             index = inline[col];
  309.          }
  310.       return(newval);
  311.       }                         /* end of octal 'else'             */
  312.  
  313.    }                        /* end of octal or hexadecimal numbers */
  314.  
  315.                                 /* find variable or function name  */
  316.    if ((inline[col] >= 'A') && (inline[col] <= 'Z')) {
  317.       name[0] = inline[col++];
  318.       i = 1;
  319.       while ((((inline[col] >= 'A') && (inline[col] <= 'Z')) ||
  320.                  ((inline[col] >= '0') && (inline[col] <= '9'))) &&
  321.                      (i <= 5)) {  /* continue var or function name */
  322.          name[i++] = inline[col++];
  323.       }
  324.       name[i] = 0;              /* name found                      */
  325.                                 
  326.       if (inline[col] == '('){  /* function call                   */
  327.          col++;
  328.          if (strcmp(name, "ABS") == 0) {
  329.             calcdata(&newval);
  330.             if (newval < 0.0) 
  331.                newval = -newval;
  332.          } else if (strcmp(name, "SQRT") == 0) {
  333.             calcdata(&newval);
  334.             if (newval < 0.0) {
  335.                errchk(5);       /* Neg value for SQRT              */
  336.                newval = 0.0;
  337.             } else 
  338.                newval = sqrt(newval);
  339.          } else if (strcmp(name, "FACT") == 0) {
  340.             calcdata(&newval);
  341.             if (newval < 0.0) {
  342.                errchk(16);      /* Neg value for FACT              */
  343.                newval = 0.0;
  344.             }
  345.             else {
  346.                double count;
  347.                int howmany;
  348.                count = newval;
  349.                newval = 1.0;
  350.                for (howmany = (int)count ; howmany > 1 ; howmany--) {
  351.                   count = howmany;
  352.                   newval = newval * count;
  353.                }
  354.             }
  355.          } else if (strcmp(name, "EXP") == 0) {
  356.             calcdata(&newval);
  357.             newval = exp(newval);
  358.          } else if (strcmp(name, "LOG") == 0) {
  359.             calcdata(&newval);
  360.             if (newval < 0.0) {
  361.                errchk(7);       /* Neg value for LOG               */
  362.                newval = 0.0;
  363.             } else newval = log(newval);
  364.          } else if (strcmp(name, "SIN") == 0){
  365.             calcdata(&newval);
  366.             newval = sin(newval);
  367.          } else if (strcmp(name, "COS") == 0){
  368.             calcdata(&newval);
  369.             newval = cos(newval);
  370.          } else if (strcmp(name, "ATAN") == 0){
  371.             calcdata(&newval);
  372.             newval = atan(newval);
  373.          } else {
  374.             errchk(6);          /* function not found              */
  375.             newval = 0.0;
  376.          }
  377.          col--;
  378.          return(newval);
  379.       }                         /* end of function call            */
  380.  
  381.       else {                    /* variable name                   */
  382.          for (i = 0 ; i < 12 ; i++) {
  383.             if ((strcmp(name, allvars[i].varname)) == 0) {
  384.                newval = allvars[i].value;
  385.                return(newval);
  386.             }
  387.          }
  388.          errchk(3);             /* variable not found              */
  389.          newval = 0.0;
  390.          return(newval);
  391.       }                         /* end of variable call            */
  392.  
  393.    }                           /* end of variable or function call */
  394.    errchk(9);
  395.    return(0.0);                 /* invalid data found              */
  396. }
  397.  
  398.  
  399.  
  400. /*********************************************************** getop */
  401. /* A call to this function expects to find an operator, end of     */
  402. /* line or a close parenthesis.                                    */
  403. char getop(void)
  404. {
  405.    while (inline[col] == ' ') 
  406.       col++;                     /* ignore blanks                  */
  407.    switch (inline[col]){
  408.       case '$':
  409.       case ')':
  410.       case  0 :
  411.       case '+':
  412.       case '-':
  413.       case '*':
  414.       case '/': break;
  415.       default : errchk(4);       /* invalid operator               */
  416.    }
  417.    return(inline[col]);
  418. }
  419.  
  420.  
  421.  
  422. /********************************************************** errchk */
  423. /* The error code is stored by this function and the cursor column */
  424. /*  is adjusted in an attempt to put the cursor near the error     */
  425. /* that caused the problem.                                        */
  426. void errchk(int err)
  427. {
  428.    if(errcode) return;           /* error already found            */
  429.    else {                        /* only the first error is stored */
  430.       errcode = err;             /* store the error number         */
  431.       switch (err) {
  432.          case 2  :
  433.          case 4  :
  434.          case 8  :
  435.          case 9  :
  436.          case 10 :
  437.          case 11 :
  438.          case 12 : colerr = col;
  439.                    break;
  440.          case 1  :
  441.          case 3  : colerr = col - 1;
  442.                    break;
  443.          case 6  : colerr = col - 2;
  444.                    break;
  445.          case 5  :
  446.          case 7  : colerr = col - 3;
  447.                    break;
  448.          default : colerr = col;
  449.       }
  450.    }
  451. }
  452.